<template>
	<div id="dialog-form">
		<HyDialog
			:title="title"
			v-model="dialogVisible"
			:width="550"
			:top="config.top || '15vh'"
			@closed="closed"
		>
			<HyForm
				:disabled="disabled"
				:model="forms"
				:rules="rules"
				ref="ruleFormDialog"
				label-position="right"
				label-width="auto"
			>
				<slot v-for="item in config.form" :key="item.key" :name="item.key" :row="item">
					<HyFormItem :label="item.label" :prop="item.key" v-if="!item.hide">
						<template v-if="item.type == 'select'">
							<HySelect
								:disabled="item.disabled"
								v-if="item.remote === true"
								v-model="forms[item.key]"
								:multiple="item.multiple"
								:placeholder="item.placeholder || '请选择'"
								:loading="selectOptions[item.key].remoteLoading"
								:remote-method="remoteMethod(item.key)"
								filterable
								remote
							>
								<HyOption
									v-for="opt in selectOptions[item.key].list"
									:key="opt.value"
									:label="opt.label"
									:value="opt.value"
								></HyOption>
							</HySelect>
							<HySelect
								:disabled="item.disabled"
								:multiple="item.multiple"
								v-else
								v-model="forms[item.key]"
								:placeholder="item.placeholder || '请选择'"
							>
								<HyOption
									v-for="opt in item.options"
									:key="opt.value"
									:label="opt.label"
									:value="opt.value"
								></HyOption>
							</HySelect>
						</template>
						<template v-else-if="item.commentsName === 'datePicker'">
							<HyDatePicker
								:disabled="item.disabled"
								v-model="forms[item.key]"
								:type="item.type"
								:placeholder="item.placeholder || '请选择'"
								:format="item.format || 'YYYY-MM-DD'"
								:value-format="item.format || 'YYYY-MM-DD'"
								:start-placeholder="item.startPlaceholder || '请选择开始日期'"
								:end-placeholder="item.endPlaceholder || '请选择结束日期'"
								:disabledDate="item.disabledDate || ''"
								:range-separator="item.disabledDate || '至'"
								:shortcuts="item.shortcuts || []"
							></HyDatePicker>
						</template>
						<template v-else-if="item.commentsName === 'timeSelect'">
							<HyTimeSelect
								:disabled="item.disabled"
								v-model="forms[item.key]"
								:start="item.start"
								:step="item.step"
								:end="item.end"
								:placeholder="item.placeholder || '请选择'"
							></HyTimeSelect>
						</template>
						<template v-else-if="item.type == 'switch'">
							<HySwitch :disabled="item.disabled" v-model="forms[item.key]"></HySwitch>
						</template>
						<template v-else-if="item.type == 'radio'">
							<HyRadioGroup v-model="forms[item.key]" :disabled="item.disabled">
								<HyRadio
									:disabled="item.disabled"
									v-for="item in item.options"
									:key="item.value"
									:label="item.value"
								>
									{{ item.label }}
								</HyRadio>
							</HyRadioGroup>
						</template>
						<template v-else-if="item.type == 'checkbox'">
							<HyCheckboxGroup v-model="forms[item.key]" :disabled="item.disabled">
								<HyCheckbox
									:disabled="item.disabled"
									v-for="item in item.options"
									:key="item.value"
									:label="item.value"
								>
									{{ item.label }}
								</HyCheckbox>
							</HyCheckboxGroup>
						</template>
						<template v-else-if="item.type == 'treeselect'">
							<HyTreeselect
								v-model="forms[item.key]"
								:dataAdaptiveMap="item.dataAdaptiveMap"
								:placeholder="item.placeholder || '请选择'"
								:treeselectList="item.reeselectData"
								:disabled="item.disabled"
							></HyTreeselect>
						</template>
						<template v-else>
							<HyInput
								:disabled="item.disabled"
								@input="inputLimiting(item.key, item.handlerLimiting)"
								v-model.trim="forms[item.key]"
								:maxlength="item.maxlength"
								:type="item.type"
								:placeholder="item.placeholder || '请选择'"
							></HyInput>
						</template>
					</HyFormItem>
				</slot>
			</HyForm>
			<template #footer>
				<span class="dialog-footer">
					<HyButton @click="close()">{{ disabled ? '关 闭' : '取 消' }}</HyButton>
					<HyButton v-show="!disabled" type="primary" @click="handlerSubmit()" :loading="loading">
						{{ loading ? '保存中...' : '确定' }}
					</HyButton>
				</span>
			</template>
		</HyDialog>
	</div>
</template>

<script lang="javascript">
	import {
		ElButton,
		ElDialog,
		ElForm,
		ElFormItem,
		ElSelect,
		ElOption,
		ElDatePicker,
		ElTimeSelect,
		ElInput,
		ElSwitch,
		ElRadioGroup,
		ElRadio,
		ElCheckbox,
		ElCheckboxGroup
	} from 'element-plus';
	import {
		reactive,
		toRefs,
		onMounted,
		getCurrentInstance,
		computed,
		watch,
		nextTick
	} from 'vue';
	import { CREATE, UPDATE, DELETE, QUERY } from '@/utils/Const';
	import HyTreeselect from '@/components/CommonTreeselectV2';
	export default {
		components : {
			HyButton : ElButton,
			HyDialog : ElDialog,
			HyForm : ElForm,
			HyFormItem : ElFormItem,
			HySelect : ElSelect,
			HyOption : ElOption,
			HyDatePicker : ElDatePicker,
			HyTimeSelect : ElTimeSelect,
			HyInput : ElInput,
			HySwitch : ElSwitch,
			HyRadioGroup : ElRadioGroup,
			HyRadio : ElRadio,
			HyCheckbox : ElCheckbox,
			HyCheckboxGroup : ElCheckboxGroup,
			HyTreeselect : HyTreeselect
		},
		props : {
			modelValue : {
				type : Object,
				required : true
			},
			config : {
				type : Object
			}
		},
		setup (ctx, context) {
			let ruleForm = null;
			let Instance = getCurrentInstance().proxy;
			// eslint-disable-next-line vue/no-setup-props-destructure
			let config = ctx.config;
			let state = reactive({
				loading : false,
				disabled : config.disabled,
				dialogVisible : config.dialogVisible,
				forms : {},
				rules : {},
				selectOptions : {}
			});

			// 标题
			let title = computed(() => {
				let type = config.type.toUpperCase();
				if (type.includes(CREATE)) {
					return '新增';
				}
				if (type.includes(DELETE)) {
					return '修改';
				}
				if (type.includes(UPDATE)) {
					return '修改';
				}
				if (type.includes(QUERY)) {
					return '查看';
				}
				return '';
			});

			let open = (params) => {
				config = params;
				state.dialogVisible = true;
				state.disabled = params.disabled;
				nextTick(() => {
					ruleForm = Instance.$refs['ruleFormDialog'];
				});
				init();
			};
			// 关闭
			let close = () => {
				ruleForm.resetFields();
				state.dialogVisible = false;
			};

			// 组件关闭后自动销毁组件
			let closed = () => {
				ruleForm.resetFields();
				config.close && config.close();
			};

			onMounted(() => {
				nextTick(() => {
					ruleForm = Instance.$refs['ruleFormDialog'];
				});
			});

			let init = () => {
				config.form.forEach((item) => {
					// 默认值
					state.forms[item.key] = item.defaultValue;
					// 组装验证器
					state.rules[item.key] = item.rules;
					// 远程搜索列表映射
					if (item.remote) {
						state.selectOptions[item.key] = {
							remoteLoading : false,
							list : []
						};
					}
					// checkbox
					if (item.defaultValue !== undefined && item.type === 'checkbox') {
						state.forms[item.key] = [];
					}
					// select 多选
					if (item.defaultValue !== undefined && item.type === 'select' && item.multiple) {
						state.forms[item.key] = [];
					}
					// 回显
					if (config.data && config.data[item.key] !== undefined) {
						let v = config.data[item.key];
						if (item.type === 'checkbox') {
							v = Array.isArray(v) ? v : [];
						}
						state.forms[item.key] = v;
					}
				});
				context.emit('update:modelValue', state.forms);
			};
			init();
			// 提交
			let handlerSubmit = () => {
				ruleForm.validate(async (valid) => {
					if (valid) {
						state.loading = true;
						let params = {};
						Object.keys(state.forms).forEach((key) => {
							if (
								state.forms[key] !== '' &&
	              state.forms[key] !== 'null' &&
	              state.forms[key] !== 'undefined' &&
	              state.forms[key] !== null &&
	              state.forms[key] !== undefined
							) {
								params[key] = state.forms[key];
							}
						});

						await config.handlerSubmit(params);
						state.loading = false;
						close();
					}
				});
			};

			// 远程搜索
			let remoteMethod = (key) => {
				let res = config.form.find((item) => item.key === key);
				return async (query) => {
					if (query !== '') {
						state.selectOptions[key].remoteLoading = true;
						state.selectOptions[key].list = await res.getOptions();
						state.selectOptions[key].remoteLoading = false;
					} else {
						state.selectOptions[key].list = [];
						state.selectOptions[key].remoteLoading = false;
					}
				};
			};

			// 输入限制
			let inputLimiting = (key, callback) => {
				if (callback) {
					state.forms[key] = callback(state.forms[key]);
				}
			};

			watch(state.forms, () => {
				context.emit('update:modelValue', state.forms);
			});

			return {
				open,
				title,
				inputLimiting,
				close,
				remoteMethod,
				handlerSubmit,
				closed,
				...toRefs(state)
			};
		}
	};
</script>

<style lang="scss">
	#dialog-form {
		.el-form-item__content,
		.el-select,
		.el-input {
			width: 380px !important;
			display: inline-block !important;
			margin-left: 0px !important;
		}
	}
</style>
